package com.example.auth.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.auth.authorization.constants.ParameterNamesEmail;
import com.example.auth.authorization.constants.ParameterNamesSms;
import com.example.auth.entity.AppClient;
import com.example.auth.service.AppClientService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.DependsOn;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.UUID;


public class CustomRegisteredClientRepository implements RegisteredClientRepository {
    AppClientService clientService;


    public CustomRegisteredClientRepository(AppClientService clientService) {
        this.clientService = clientService;
    }

    /**
     * 这里直接调用AppClientService的接口存储了 不在这里调用
     * @param registeredClient the {@link RegisteredClient}
     */
    @Override
    public void save(RegisteredClient registeredClient) {

        System.out.println("1222222222223");
    }

    @Override
    public RegisteredClient findById(String id) {
        AppClient client = clientService.getById(id);
        RegisteredClient registeredClient = appClientToRegisteredClient(client);
        return registeredClient;
    }

    @Override
    public RegisteredClient findByClientId(String clientId) {
        AppClient client = clientService.getOne(new LambdaQueryWrapper<AppClient>().eq(AppClient::getClientId, clientId));
        RegisteredClient registeredClient = appClientToRegisteredClient(client);
        return registeredClient;
    }


    protected RegisteredClient appClientToRegisteredClient(AppClient appClient){

        TokenSettings tokenSettings = TokenSettings.builder()
                .accessTokenTimeToLive(Duration.ofHours(appClient.getAccessTokenTimeToLive()))
                .refreshTokenTimeToLive(Duration.ofHours(appClient.getRefreshTokenTimeToLive()))
                .reuseRefreshTokens(appClient.getReuseRefreshTokens())
                .build();
        RegisteredClient build = RegisteredClient.withId(appClient.getId().toString())
                .tokenSettings(tokenSettings)
                .clientId(appClient.getClientId())
                .clientName(appClient.getClientName())
                .clientSecret(appClient.getClientSecret())
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
                .authorizationGrantTypes(set -> {
                    String authorizationGrantTypes = appClient.getAuthorizationGrantTypes();
                    if (authorizationGrantTypes != null) {
                        for (String grantType : authorizationGrantTypes.split(",")) {
                            set.add(new AuthorizationGrantType(grantType.trim()));
                        }
                    }
                })
                .redirectUri(appClient.getRedirectUris())
                .postLogoutRedirectUri(appClient.getPostLogoutRedirectUris())
                .scope(OidcScopes.OPENID)
                .scope(OidcScopes.PROFILE)
                .scopes(set -> {
                    String scopes = appClient.getScopes();
                    for (String scope : scopes.split(",")) {
                        set.add(scope);
                    }
                })
                .clientSettings(ClientSettings.builder().requireAuthorizationConsent(appClient.getRequireApprove()).build())
                .build();
        return build;
    }
}
